﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.IO;
using COFE.Core;
using COFE.Core.Utils;
using COFE.Core.Filter;
using System.Diagnostics;
using COFE.Data;

namespace COFE.Web.Services
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class SearchServices : ISearchServices
    {
        
        public Stream GetSearchResult(string json, string filterStr)
        {
            var jsonFilter = WSFilterUtils.GetQueryAsFilter("filter", "json");
            filterStr = (filterStr == null) ? jsonFilter :
                        filterStr + " " + jsonFilter;

            return ServicesUtils.ExecuteAndReturn
                <string, Tuple<IEntryFilter[], IOptionFilter[]>, Stream>(
                (fStr) =>
                {                    
                    IEntryFilter[] entryFilters;
                    IOptionFilter[] optionFilters;
                    COFEShared.FilterParser.ParseFilter(fStr,
                        out entryFilters, out optionFilters);
                    if (!(optionFilters.Any(f => f is SearchSourceOptionFilter)))
                        optionFilters = optionFilters.Concat(
                            new List<IOptionFilter>()
                            {
                                new SearchSourceOptionFilter(SearchSourceType.Cache)
                            }).ToArray();
                    return new Tuple<IEntryFilter[], IOptionFilter[]>(
                        entryFilters, optionFilters);
                },
                (filters, fStr) =>
                {
                    EntryList result = EntryList.FromCOFE(
                    new COFE.Core.AutoEntryList(Guid.Empty, null,
                      filters.Item1, filters.Item2));
                    return EncodeObjectUtils.EncodeObject(result, json);

                },
                (filters, fStr) =>
                {
                    var so = filters.Item2.FirstOrDefault(
                        lf => lf is SearchOptionOptionFilter) as SearchOptionOptionFilter;
                    if (so == null || so.SearchOption != SearchOptionEx.TopDirectoryOnly)
                        return DateTime.Now;
                    var rfs = filters.Item1.Where(ef => ef is Core.Filter.RootEntryFilter)
                        .Cast<Core.Filter.RootEntryFilter>();
                    DateTime lastUpdateTime = DateTime.MinValue;
                    foreach (var rf in rfs)
                        if (rf.Directory != null)
                        {
                            DateTime lastUpdateLocal = rf.Directory.InternalProperties
                                .GetProperty(DatabaseProperties.LastListTime).ValueAsUtcDateTime;
                            if (lastUpdateTime < lastUpdateLocal)
                                lastUpdateTime = lastUpdateLocal;
                        }                       
                    return lastUpdateTime;
                }, filterStr, true
                );
        }
    }
}